var Facebook = new Class({
	
	api_key : '',
	secret_key : '',
	token : '',
	session_key : '',
	uid : '',
	secret : '',
	call_id : '',
	v: '1.0',
	ready : 0, // 0 if no token, 1 if token but no session, 2 if session exists.
	debug : 1,
	
    initialize: function(api_key, secret_key, callback){
        this.api_key = api_key;
        this.secret_key = secret_key;
        this.ready = 0;
        this.createToken(callback);
    },
    
    getFriends: function(callback) {
		var request = {
			'method': 'facebook.friends.get' 
		};
        var parse = function(res) {
			var xml = loadXML(res);
			var friends = [];
			if(xml.tagName == 'friends_get_response') {
		        for(var i = 0; i < xml.childNodes.length; i++) {
		            if(xml.childNodes[i].tagName == 'uid')
		                friends.push(xml.childNodes[i].text);
		        }
		    } else
		        this.xmlError(xml);
		    callback(friends);
		};
		return this.sessionCall(request, parse.bind(this));
    },
        
    getInfo: function(uids, fields, callback) {
		var request = {
			'method': 'facebook.users.getInfo',
			'uids': uids,
			'fields': fields
		};
        var parse = function(res) {
			var xml = loadXML(res);
			var people = [];
			if(xml.tagName == 'users_getInfo_response') {
		        for(var i = 0; i < xml.childNodes.length; i++) {
		            if(xml.childNodes[i].tagName == 'user') {
		            	var userNode = xml.childNodes[i];
		            	for(var j = 0; j < userNode.childNodes.length; j++) {
		            		if(userNode.childNodes[j].tagName == 'uid') {
		            			people.push(new Object());
		            		} else
		            			people[people.length - 1][userNode.childNodes[j].tagName] = userNode.childNodes[j].text;
		            	}
		            }
		        }
		    } else
		        this.xmlError(xml);
		    callback(people);
		};
		return this.sessionCall(request, parse.bind(this));
    },
    
    createToken: function(callback) {
		var createTokenRequest = { 
			'api_key' : this.api_key, 
			'v' : this.v, 
			'method': 'facebook.auth.createToken' 
		};
		var parse = function(res) {
			var xml = loadXML(res);
		    if(xml.tagName == 'auth_createToken_response') {
			    this.token = xml.text;
                this.ready = 1;
            }
			// then getSession
		    this.showLoginWindow();
		    callback();
		};
		return this.methodCall(createTokenRequest, parse.bind(this));
    },
    getSession: function(callback) {	
        if(this.ready < 1) {
            this.logError('Must have a token prior to calling function');
            return;
        }
            
		var getSessionRequest = { 
			'api_key' : this.api_key, 
			'v' : this.v, 
			'method': 'facebook.auth.getSession',
			'auth_token': this.token
		};
		var parse = function(res) {
			var xml = loadXML(res);
		    if(xml.tagName == 'auth_getSession_response') {
		        if(xml.childNodes.length == 0)
		            this.xmlError(xml);
		        for(var i = 0; i < xml.childNodes.length; i++) {
		            if(xml.childNodes[i].tagName == 'session_key')
		                this.session_key = xml.childNodes[i].text;
		            else if(xml.childNodes[i].tagName == 'uid')
		                this.uid = xml.childNodes[i].text;
		            else if(xml.childNodes[i].tagName == 'secret')
		                this.secret = xml.childNodes[i].text;
		        }
                this.ready = 2;
		    } else
		        this.xmlError(xml);
		    callback();
		};
		return this.methodCall(getSessionRequest, parse.bind(this), {'https':true} );
    },
    showLoginWindow: function() {
		var loginRequest = { 
			'api_key' : this.api_key, 
			'auth_token' : this.token,
			'v' : this.v, 
			'popup': '1'
		};
        window.open('http://www.facebook.com/login.php?' + Object.toQueryString(loginRequest), 
            'facebook_login', 'toolbar=0,scrollbars=0,location=0,statusbar=0,menubar=0,resizable=0,width=626,height=436');
    },
    
    sessionCall: function(args, fcn, options) {
        if(this.ready < 2) {
            this.logError('Must have a token/session_id prior to calling function');
            return;
        }
        var date = new Date();
        if(!args.api_key)
            args.api_key = this.api_key;
        if(!args.call_id)
            args.call_id = date.getTime();
        if(!args.session_key)
            args.session_key = this.session_key;
        if(!args.v)
            args.v = this.v;
        
        this.methodCall(args, fcn, options);
    },
    
    methodCall: function(args, fcn, options) {
        var url = "http://api.facebook.com/restserver.php?";
        if(options) {
            if(options.https) 
                url = "https://api.facebook.com/restserver.php?";
        }
        var secret = this.secret_key;
        if(args.session_key)
        	secret = this.secret;
		var queryString = [];
//		for (var property in args) queryString.push(encodeURIComponent(property)+'='+encodeURIComponent(args[property]));
		for (var property in args) queryString.push(property+'='+args[property]);
		queryString.sort();
    	this.logDebug('sig::=' + queryString.join('') + secret);
		queryString.push('sig=' + hex_md5(queryString.join('') + secret));
    	new Ajax(url + queryString.join('&'), {method: 'post', onSuccess:fcn}).request();
    	this.logDebug(url + queryString.join('&'));
    },
    logError: function(s) {
    	$('errors').innerHTML += s + '<br />';
    },
    logDebug: function(s) {
    	if(this.debug) {
    		$('errors').innerHTML += s + '<br />';
    	}
    },
    /* the xml was not what we expected, parse the error message */
    xmlError: function(xml) {
    	alert('error:' + xml.xml);
    }
});
